;*****************************************************************************************************
;+
; NAME:
;       IGL_CONTOUR
;
; PURPOSE:
;
;       This is a basic vizualisation object which represents a contour
;       plot. It is subclassed from IGL_BaseRangeObject to have all
;       the necessary pan/zoom behaviour for interactivity.
;
;
; AUTHORS:
;
;        RAPHAEL SADOUN
;        Graduate Student
;        Institut d'Astrophysique de Paris
;        98 bis boulevard Arago
;        75014 PARIS FRANCE
;        E-mail: raphael.sadoun@gmail.com
;
; SUPERCLASSES:
;
;       IGL_BASERANGEOBJECT
;
; SYNTAX:
;
;       contour = Obj_New('IGL_Contour')
;
;
; CLASS_STRUCTURE:
;
;          class = {IGL_Contour, $
;            INHERITS IGL_BASERANGEOBJECT, $ ; This is an IGL_BASERANGEOBJECT subclass
;            zdata:ptr_new(), $              ; The values of the contour surface
;            xdata:ptr_new(), $              ; The x coordinates of the contour surface          
;            ydata:ptr_new(), $              ; The y coordinates of the contour surface
;            color:'', $                     ; The color of the contour lines            
;            thick:0.0, $                    ; The thickness of the contour lines
;            c_annotation:ptr_new(), $       ; The annotation of each contour level
;            c_charsize:ptr_new(), $         ; The character size of the annotations            
;            c_charthick:ptr_new(), $        ; The character thickness of the annotations
;            c_colors:ptr_new(), $           ; The color of each contour level
;            c_labels:ptr_new(), $           ; The annotation flag of each contour level
;            c_linestyle:ptr_new(), $        ; The line style of each contour level
;            c_thick:ptr_new(), $            ; The thickness of each contour level
;            levels:ptr_new(), $             ; The value of the contour levels
;            nlevels:0L, $                   ; The number of contour levels            
;            type:0B, $                      ; The type (normal, fill or cell_fill) of the contour surface
;            closed:0B, $                    ; Flag indicating if the contour lines are closed
;            downhill:0B, $                  ; Flag indicating if downhill marks are drawn
;            font:0B, $                      ; The character font for the annotations
;            clip:0B, $                      ; Flag indicating if the contour is clipped
;            visible:0B $                    ; Flag indicating if the contour is visible or not
;           }
;
;
; MODIFICATION_HISTORY:
;
;       Written by: Raphael Sadoun, 24 April 2012
;-
;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::CONTROLPANEL
;
; PURPOSE:
;
;       This method creates a control panel for the graphic.
;
; SYNTAX:
;
;       self -> ControlPanel, baseObject
;
; ARGUMENTS:
;
;       baseObject:    The object reference of a base widget for this control to
;                      be added to. If not supplied, the control panel will be in a
;                      self contained window.
;
; KEYWORDS:
;
;       _EXTRA:       Any keywords appropriate for the CATCONTROLPANEL::INIT method.
;-
;*****************************************************************************************************
PRO IGL_Contour::ControlPanel, baseObject, _EXTRA=extraKeywords

   @cat_pro_error_handler

   ;; Create a new control panel
   cp = OBJ_NEW ('CatControlPanel', self, PARENT=baseObject, COLUMN=1, $
      TITLE='IGL_Contour Control Panel', _EXTRA=extraKeywords, /No_Cancel, /No_Apply, /No_OK)

   IF (NOT OBJ_VALID (cp)) THEN RETURN
   
   aproperties = Obj_New('PROPERTYSHEETWIDGET', cp, Value=self, Name='IGL_CONTOUR PROPERTYSHEET', YSize=17)
   aproperties -> SetProperty, Event_Object=self

   ;; Display the control panel if it created its own TLB.
   IF cp -> Created_Own_TLB(tlb) THEN tlb -> Draw, /Center

   self -> Report, /Completed

END


;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::DRAW
;
; PURPOSE:
;
;       This method draws the contour plot in the current display window.
;
; SYNTAX:
;
;       self -> Draw
;
; ARGUMENTS:
;
;       None.
;
; KEYWORDS:
;
;       _EXTRA:     Any keyword accepted by the CATATOM::Draw method.
;
;-
;*****************************************************************************************************
PRO IGL_Contour::Draw, _Extra=extrakeywords

   @cat_pro_error_handler

   ;; If the object is invisible, then return immediately.
   IF self.visible EQ 0 THEN RETURN

   ;; Make sure the data is valid
   IF PTR_VALID(self.zdata) EQ 0 THEN RETURN
   IF PTR_VALID(self.xdata) EQ 0 THEN RETURN
   IF PTR_VALID(self.ydata) EQ 0 THEN RETURN

   ;; Save the IDL plot variables
   cx = !x
   cy = !y
   cz = !z

   ;; Apply the coordinate system.
   self -> ApplyCoords

   ;; Save current color table
   TVLCT, r, g, b, /get

   ;; Switch to indexed color
   SetDecomposedState, 0, currentstate=currentstate

   ;; Calculate the scale factor for the line thickness
   IF !D.name EQ 'PS' THEN factor = 2.5 ELSE factor = 1.0
   IF N_Elements(*self.c_charthick) GT 0 THEN c_charthick = (*self.c_charthick)*factor
   IF N_Elements(*self.c_thick) GT 0 THEN c_thick = (*self.c_thick)*factor

   ;; Switch to hardware fonts if we are in PostScript and the
   ;; requested font is Herschey
   IF (!D.Name EQ 'PS') AND (self.font EQ 0) THEN font = 1 ELSE font = self.font
   
   ; Draw the object here.
   self._coords -> GetProperty, xrange=xrange, yrange=yrange, position=position, xlog=xlog, ylog=ylog
   IF (position[0] GE position[2]) THEN return
   IF (position[1] GE position[3]) THEN return
   IF N_ELEMENTS(*self.c_colors) NE 0 THEN BEGIN      
      IF size(*self.c_colors,/TNAME) EQ 'STRING' THEN c_colors = cgcolor(*self.c_colors) ELSE c_colors=*self.c_colors
   ENDIF
   IF self.type EQ 0 THEN color = cgcolor(self.color,!d.table_size-2) ; We pollute the color table only if it is not a filled contour
   CONTOUR, *self.zdata, *self.xdata, *self.ydata, $
            position=position, $
            xrange=xrange, $
            yrange=yrange, $
            xlog=xlog, $
            ylog=ylog, $
            xstyle=5, $
            ystyle=5, $
            color=color, $
            thick=self.thick*factor, $
            noclip=1-keyword_set(self.clip), $
            fill=(self.type EQ 1), $
            cell_fill=(self.type EQ 2), $
            closed=self.closed, $
            downhill=self.downhill, $
            levels=*self.levels, $
            c_annotation=*self.c_annotation, $
            c_charsize=*self.c_charsize, $
            c_charthick=c_charthick, $
            c_colors=c_colors, $
            c_labels=*self.c_labels, $
            c_linestyle=*self.c_linestyle, $
            c_thick=c_thick, $
            font=font-1, $
            /noerase

   ;; Save the coordinate system
   !igl_x = !x
   !igl_y = !y
   !igl_z = !z

   ;; Restore the IDL plot variables
   !x = cx
   !y = cy
   !z = cz

   ;; Restore the decomposed state
   SetDecomposedState, currentstate

   ;; Restore color table
   TVLCT, r, g, b

   ;; Draw the children
   self -> CatAtom::Draw, _EXTRA=extra

   ;; Report completion
   self -> Report, /Completed

END

;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::EVENTHANDLER
;
; PURPOSE:
;
;       This method is an event handler for the Control Panel.
;
; SYNTAX:
;
;       Called automatically by the event handling system
;
; ARGUMENTS:
;
;       event:  The event structure.
;
; KEYWORDS:
;
;       None.
;-
;*****************************************************************************************************
PRO IGL_Contour::EventHandler, event

   @cat_pro_error_handler

   ; Get the name of the widget generating the event. Branch on this.
   event.ID -> GetProperty, Name=eventName
   
   CASE eventName OF

      'IGL_CONTOUR PROPERTYSHEET': BEGIN

         IF event.type EQ 0 THEN BEGIN
            
            CASE StrUpCase(event.identifier) OF

               'COLOR': BEGIN

                  event.component -> GetProperty, Color=color
                  event.id -> GetProperty, ID=group_leader
                  color = PickColorName(color, Group_Leader=group_leader)
                  event.component -> SetProperty, Color=color

                  ;; Refresh graphic hierarchy
                  IGL_RefreshDraw, event.component, /Buffered_Output

               END

               ELSE: BEGIN

                  component = event.component
                  identifier = event.identifier
                  event.id -> GetProperty, Value=value, Component=component, Property_Value=identifier
                  event.component -> SetPropertyByIdentifier, identifier, value
                  
                  ;; Refresh graphic hierarchy
                  IF OBJ_VALID(event.component) THEN IGL_RefreshDraw, event.component, /Buffered_Output

               END

            ENDCASE

         ENDIF ; of BUTTON DOWN EVENT

         END 

        ; If you can't handle the event here. Pass it along to superclass EventHandler
        ELSE: self -> IGL_BASERANGEOBJECT::EventHandler, event

   ENDCASE

   ;; Report completion
   IF Obj_Valid(self) THEN self -> Report, /Completed

END


;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::GETPROPERTY
;
; PURPOSE:
;
;       This method is used to get the object's properties.
;
; SYNTAX:
;
;       self -> GetProperty
;
; ARGUMENTS:
;
;     None.
;
; KEYWORDS:
;
;    ZDATA:        The values of the contour surface. If not provided,
;                  set to the default value of FLTARR(2,2).
;
;    XDATA:        The x coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[1]).
;               
;    YDATA:        The y coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[2]).
;
;    COLOR:        The color of the contour lines.
;               
;    THICK:        The thickness of the contour lines.
;               
;    C_ANNOTATION: The annotation of each contour level.
;               
;    C_CHARSIZE:   The character size of the annotations.
;               
;    C_CHARTHICK:  The character thickness of the annotations.
;               
;    C_COLORS:     The color of each contour level.
;               
;    C_LABELS:     The annotation flag of each contour level.
;               
;    C_LINESTYLE:  The line style of each contour level.
;               
;    C_THICK:      The thickness of each contour level.
;               
;    LEVELS:       The value of the contour levels.
;               
;    NLEVELS:      The number of contour levels.
;
;    FONT:         The character font for the annotations.
;
;    CLOSED:       Flag indicating if the contour lines are closed.
;               
;    DOWNHILL:     Flag indicating if downhill marks are drawn.
;               
;    CLIP:         Flag indicating if the contour is clipped.
;               
;    TYPE:         The type (0=normal, 1=fill or 2=cell_fill) of the
;                  contour plot.
;
;    VISIBLE:      Flag indicating if the contour plot is visible.
;
;     _REF_EXTRA:  Any keywords appropriate for the superclass GetProperty method.
;-
;*****************************************************************************************************
PRO IGL_Contour::GetProperty, ZDATA=zdata, $
                              XDATA=xdata, $
                              YDATA=ydata, $
                              FONT=font, $
                              COLOR=color, $
                              THICK=thick, $
                              C_ANNOTATION=c_annotation, $
                              C_CHARSIZE=c_charsize, $
                              C_CHARTHICK=c_charthick, $
                              C_COLORS=c_colors, $
                              C_LABELS=c_labels, $
                              C_LINESTYLE=c_linestyle, $
                              C_THICK=c_thick, $
                              LEVELS=levels, $
                              NLEVELS=nlevels, $
                              CLOSED=closed, $
                              DOWNHILL=downhill, $
                              CLIP=clip, $
                              TYPE=type, $
                              VISIBLE=visible, $
                              _REF_EXTRA=extraKeywords

   @cat_pro_error_handler

   IF (arg_present(zdata)) THEN zdata = *self.zdata
   IF (arg_present(xdata)) THEN xdata = *self.xdata
   IF (arg_present(ydata)) THEN ydata = *self.ydata
   IF (arg_present(color)) THEN color = self.color
   IF (arg_present(thick)) THEN thick = self.thick
   IF (arg_present(c_annotation)) THEN c_annotation = *self.c_annotation
   IF (arg_present(c_charsize)) THEN c_charsize = *self.c_charsize
   IF (arg_present(c_charthick)) THEN c_charthick = *self.c_charthick
   IF (arg_present(c_colors)) THEN c_colors = *self.c_annotation
   IF (arg_present(c_labels)) THEN c_labels = *self.c_labels
   IF (arg_present(c_linestyle)) THEN c_linestyle = *self.c_linestyle
   IF (arg_present(c_thick)) THEN c_thick = *self.c_thick
   IF (arg_present(levels)) THEN levels = *self.levels
   IF (arg_present(nlevels)) THEN nlevels = self.nlevels
   IF (arg_present(closed)) THEN closed = self.closed
   IF (arg_present(downhill)) THEN downhill = self.downhill
   IF (arg_present(font)) THEN font = self.font
   IF (arg_present(clip)) THEN clip = self.clip
   IF (arg_present(type)) THEN type = self.type
   IF (arg_present(visible)) THEN visible = self.visible

   IF (N_ELEMENTS (extraKeywords) GT 0) THEN self -> IGL_BASERANGEOBJECT::GetProperty, _EXTRA=extraKeywords

   ;; Report completion
   self -> Report, /Completed

END

;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::SETPROPERTY
;
; PURPOSE:
;
;       This method is used to set the object's properties.
;
; SYNTAX:
;
;       self -> SetProperty
;
; ARGUMENTS:
;
;     None.
;
; KEYWORDS:
;
;    ZDATA:        The values of the contour surface. If not provided,
;                  set to the default value of FLTARR(2,2).
;
;    XDATA:        The x coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[1]).
;               
;    YDATA:        The y coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[2]).
;
;    COLOR:        The color of the contour lines.
;               
;    THICK:        The thickness of the contour lines.
;               
;    C_ANNOTATION: The annotation of each contour level.
;               
;    C_CHARSIZE:   The character size of the annotations.
;               
;    C_CHARTHICK:  The character thickness of the annotations.
;               
;    C_COLORS:     The color of each contour level.
;               
;    C_LABELS:     The annotation flag of each contour level.
;               
;    C_LINESTYLE:  The line style of each contour level.
;               
;    C_THICK:      The thickness of each contour level.
;               
;    LEVELS:       The value of the contour levels.
;               
;    NLEVELS:      The number of contour levels.
;
;    CLOSED:       Flag indicating if the contour lines are closed.
;               
;    DOWNHILL:     Flag indicating if downhill marks are drawn.
;
;    FONT:         The character font for the annotations.
;               
;    CLIP:         Flag indicating if the contour is clipped.
;               
;    TYPE:         The type (0=normal, 1=fill or 2=cell_fill) of the
;                  contour plot.
;
;    VISIBLE:      Flag indicating if the contour plot is visible.
;
;    _EXTRA:       Any keyword accepted by the SetProperty method of
;                  the IGL_BASERANGEOBJECT superclass.
;-
;*****************************************************************************************************
PRO IGL_Contour::SetProperty, ZDATA=zdata, $
                              XDATA=xdata, $
                              YDATA=ydata, $
                              COLOR=color, $
                              THICK=thick, $
                              FONT=font, $
                              C_ANNOTATION=c_annotation, $
                              C_CHARSIZE=c_charsize, $
                              C_CHARTHICK=c_charthick, $
                              C_COLORS=c_colors, $
                              C_LABELS=c_labels, $
                              C_LINESTYLE=c_linestyle, $
                              C_THICK=c_thick, $
                              LEVELS=levels, $
                              NLEVELS=nlevels, $
                              CLOSED=closed, $
                              DOWNHILL=downhill, $
                              CLIP=clip, $
                              TYPE=type, $
                              VISIBLE=visible, $
                              _EXTRA=extraKeywords

   @cat_pro_error_handler

   IF N_ELEMENTS(zdata) NE 0 THEN BEGIN
      PTR_FREE, self.zdata
      self.zdata = PTR_NEW(zdata,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(xdata) NE 0 THEN BEGIN
      PTR_FREE, self.xdata
      self.xdata = PTR_NEW(xdata,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(ydata) NE 0 THEN BEGIN
      PTR_FREE, self.ydata
      self.ydata = PTR_NEW(ydata,/ALLOCATE_HEAP)
   ENDIF

   IF N_ELEMENTS(c_annotation) NE 0 THEN BEGIN
      PTR_FREE, self.c_annotation
      self.c_annotation = PTR_NEW(c_annotation,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_charsize) NE 0 THEN BEGIN
      PTR_FREE, self.c_charsize
      self.c_charsize = PTR_NEW(c_charsize > 0.1,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_charthick) NE 0 THEN BEGIN
      PTR_FREE, self.c_charthick
      self.c_charthick = PTR_NEW(c_charthick > 1,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_colors) NE 0 THEN BEGIN
      PTR_FREE, self.c_colors
      self.c_colors = PTR_NEW(c_colors,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_labels) NE 0 THEN BEGIN
      PTR_FREE, self.c_labels
      self.c_labels = PTR_NEW(c_labels,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_linestyle) NE 0 THEN BEGIN
      PTR_FREE, self.c_linestyle
      self.c_linestyle = PTR_NEW(0 > c_linestyle < 6,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(c_thick) NE 0 THEN BEGIN
      PTR_FREE, self.c_thick
      self.c_thick = PTR_NEW(c_thick > 1,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(levels) NE 0 THEN BEGIN
      PTR_FREE, self.levels
      self.levels = PTR_NEW(levels,/ALLOCATE_HEAP)
   ENDIF
   IF N_ELEMENTS(nlevels) NE 0 THEN BEGIN
      self.nlevels = nlevels > 1
      mindata = min(*self.zdata,max=maxdata,/NAN)
      IF self.nlevels GT 1 THEN levels = (maxdata-mindata)/float(self.nlevels)*lindgen(self.nlevels)+mindata $
      ELSE levels = 0.5*(mindata+maxdata)
      PTR_FREE, self.levels
      self.levels = PTR_NEW(levels,/ALLOCATE_HEAP)
   ENDIF

   IF (n_elements(color) NE 0) THEN BEGIN
      self.color = color
      self -> SetPropertyAttribute, 'COLOR', USERDEF=CapFirstLetter(self.color)
      IF Obj_Valid(self._controlpanel) THEN self._controlpanel -> Refresh_Properties, Properties='COLOR'
   ENDIF
   IF (n_elements(thick) NE 0) THEN self.thick = thick > 1
   IF (n_elements(type) NE 0) THEN self.type = 0 > type < 2
   IF (n_elements(font) NE 0) THEN self.font = 0 > font < 2
   IF (n_elements(downhill) NE 0) THEN self.downhill = keyword_set(downhill)
   IF (n_elements(closed) NE 0) THEN self.closed = keyword_set(closed)
   IF (n_elements(clip) NE 0) THEN self.clip = keyword_set(clip)
   IF (n_elements(visible) NE 0) THEN self.visible = keyword_set(visible)
   
   IF (N_ELEMENTS (extraKeywords) GT 0) THEN self -> IGL_BASERANGEOBJECT::SetProperty, _EXTRA=extraKeywords

   ;; Report completion
   IF OBJ_VALID(self) THEN self -> Report, /Completed

END


;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::CLEANUP
;
; PURPOSE:
;
;       This is the IGL_Contour object class destructor method.
;
; SYNTAX:
;
;       Called automatically when the object is destroyed.
;
;
; ARGUMENTS:
;
;     None.
;
; KEYWORDS:
;
;     None.
;-
;*****************************************************************************************************
PRO IGL_Contour::CLEANUP

   @cat_pro_error_handler

   PTR_FREE, self.zdata
   PTR_FREE, self.xdata
   PTR_FREE, self.ydata
   PTR_FREE, self.c_annotation
   PTR_FREE, self.c_charsize
   PTR_FREE, self.c_charthick
   PTR_FREE, self.c_colors
   PTR_FREE, self.c_labels
   PTR_FREE, self.c_linestyle
   PTR_FREE, self.c_thick
   PTR_FREE, self.levels

   self -> IGL_BASERANGEOBJECT::CLEANUP
   
   self -> Report, /Completed

END

;*****************************************************************************************************
;+
; NAME:
;       IGL_Contour::INIT
;
; PURPOSE:
;
;       This is the IGL_Contour object class creator method.
;
; SYNTAX:
;
;       Called automatically when the object is created.
;
; ARGUMENTS:
;
;     None.
;
; KEYWORDS:
;
;    ZDATA:        The values of the contour surface. If not provided,
;                  set to the default value of FLTARR(2,2).
;
;    XDATA:        The x coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[1]).
;               
;    YDATA:        The y coordinates of the contour surface. If not
;                  provided, set to the default value of FINDGEN(size(zdata)[2]).
;
;    COLOR:        The color of the contour lines.
;               
;    THICK:        The thickness of the contour lines.
;               
;    C_ANNOTATION: The annotation of each contour level.
;               
;    C_CHARSIZE:   The character size of the annotations.
;               
;    C_CHARTHICK:  The character thickness of the annotations.
;               
;    C_COLORS:     The color of each contour level.
;               
;    C_LABELS:     The annotation flag of each contour level.
;               
;    C_LINESTYLE:  The line style of each contour level.
;               
;    C_THICK:      The thickness of each contour level.
;               
;    LEVELS:       The value of the contour levels.
;               
;    NLEVELS:      The number of contour levels.
;
;    FONT:         The character font for the annotations.
;
;    CLOSED:       Flag indicating if the contour lines are closed.
;               
;    DOWNHILL:     Flag indicating if downhill marks are drawn.
;               
;    CLIP:         Flag indicating if the contour is clipped.
;               
;    TYPE:         The type (0=normal, 1=fill or 2=cell_fill) of the
;                  contour plot.
;
;    _EXTRA:       Any keyword accepted by the IGL_BASERANGEOBJECT::Init method.
;
;-
;*****************************************************************************************************
FUNCTION IGL_Contour::INIT, ZDATA=zdata, $
                            XDATA=xdata, $
                            YDATA=ydata, $
                            COLOR=color, $
                            THICK=thick, $
                            FONT=font, $
                            C_ANNOTATION=c_annotation, $
                            C_CHARSIZE=c_charsize, $
                            C_CHARTHICK=c_charthick, $
                            C_COLORS=c_colors, $
                            C_LABELS=c_labels, $
                            C_LINESTYLE=c_linestyle, $
                            C_THICK=c_thick, $
                            LEVELS=levels, $
                            NLEVELS=nlevels, $
                            CLOSED=closed, $
                            DOWNHILL=downhill, $
                            CLIP=clip, $
                            TYPE=type, $
                            _EXTRA=extraKeywords

   @cat_func_error_handler

   ;; Initialize the global system variables
   IGL_InitSysVars

   ;; Default keyword values
   IF (n_elements(zdata) EQ 0) THEN zdata = fltarr(2,2)
   dims = size(zdata)
   IF (dims[0] LT 2) THEN message, 'Array must have 2 dimensions'
   nx = dims[1]
   ny = dims[2]
   IF (n_elements(ydata) EQ 0) THEN ydata = findgen(nx)
   IF (n_elements(xdata) EQ 0) THEN xdata = findgen(ny)
   IF (n_elements(color) EQ 0) THEN color = !IGL_P.color
   IF (n_elements(thick) EQ 0) THEN thick = (!IGL_P.thick EQ 0) ? 1: !IGL_P.thick
   IF (n_elements(font) EQ 0) THEN font = !IGL_P.font+1
   IF (n_elements(clip) EQ 0) THEN clip = 1-keyword_set(!IGL_P.noclip)
   IF (n_elements(type) EQ 0) THEN type = 0
   IF (n_elements(nlevels) EQ 0) THEN IF n_elements(levels) EQ 0 THEN nlevels = 6 ELSE nlevels = n_elements(levels)
   IF (n_elements(levels) EQ 0) THEN BEGIN
      mindata = MIN(zdata,max=maxdata,/NAN)
      IF nlevels GT 1 THEN levels = (maxdata-mindata)/float(nlevels)*lindgen(nlevels)+mindata $
      ELSE levels = 0.5*(mindata+maxdata)
   ENDIF
   
   ;; Initialize the superclasses
   ok = self -> IGL_BASERANGEOBJECT::Init(NAME='Contour', $
                                          DESCRIPTION='Contour surface', $
                                          _EXTRA=extraKeywords)
   
   IF (NOT ok) THEN RETURN, 0


   ; Load object.
   self.zdata = ptr_new(zdata,/allocate_heap)
   self.xdata = ptr_new(xdata,/allocate_heap)
   self.ydata = ptr_new(ydata,/allocate_heap)
   self.color = color
   self.thick = thick > 1
   self.c_annotation = ptr_new(c_annotation,/allocate_heap)
   self.c_charsize = ptr_new(c_charsize,/allocate_heap)
   self.c_charthick = ptr_new(c_charthick,/allocate_heap)
   self.c_colors = ptr_new(c_colors,/allocate_heap)
   self.c_labels = ptr_new(c_labels,/allocate_heap)
   self.c_linestyle = ptr_new(c_linestyle,/allocate_heap)
   self.c_thick = ptr_new(c_thick,/allocate_heap)
   self.levels = ptr_new(levels,/allocate_heap)
   self.nlevels = nlevels > 1
   self.closed = keyword_set(closed)
   self.downhill = keyword_set(downhill)
   self.clip = keyword_set(clip)
   self.type = 0 > type < 2
   self.font = 0 > font < 2
   self.visible = 1

   ; Register properties for the property sheet.
   self -> SetPropertyAttribute, 'name', sensitive=0
   self -> SetPropertyAttribute, 'description', sensitive=0
   self -> RegisterProperty, 'CLIP', /boolean, name='Clipping'
   self -> RegisterProperty, 'COLOR', 0, name='Color', userdef=CapFirstLetter(self.color)
   self -> RegisterProperty, 'CLOSED', /boolean, name='Closed lines'
   self -> RegisterProperty, 'TYPE', name='Contour Type', enumlist=['Normal','Filled','Cell Filled']
   self -> RegisterProperty, 'DOWNHILL', /boolean, name='Downhill Marks'
   self -> RegisterProperty, 'THICK', name='Line Thickness', /integer, valid_range=[1,10]
   self -> RegisterProperty, 'NLEVELS', name='Number of contour level', /integer, valid_range=[1,100]

   ;; Report completion
   self -> Report, /Completed

   RETURN, 1

END


;*****************************************************************************************************
;
; NAME:
;       IGL_CONTOUR CLASS DEFINITION
;
; PURPOSE:
;
;       This is the IGL_Contour object's structure definition code.
;
;*****************************************************************************************************
PRO IGL_Contour__Define, class

  COMPILE_OPT idl2, HIDDEN

   class = {IGL_Contour, $
            INHERITS IGL_BASERANGEOBJECT, $ ; This is an IGL_BASERANGEOBJECT subclass
            zdata:ptr_new(), $              ; The values of the contour surface
            xdata:ptr_new(), $              ; The x coordinates of the contour surface          
            ydata:ptr_new(), $              ; The y coordinates of the contour surface
            color:'', $                     ; The color of the contour lines            
            thick:0.0, $                    ; The thickness of the contour lines
            c_annotation:ptr_new(), $       ; The annotation of each contour level
            c_charsize:ptr_new(), $         ; The character size of the annotations            
            c_charthick:ptr_new(), $        ; The character thickness of the annotations
            c_colors:ptr_new(), $           ; The color of each contour level
            c_labels:ptr_new(), $           ; The annotation flag of each contour level
            c_linestyle:ptr_new(), $        ; The line style of each contour level
            c_thick:ptr_new(), $            ; The thickness of each contour level
            levels:ptr_new(), $             ; The value of the contour levels
            nlevels:0L, $                   ; The number of contour levels            
            type:0B, $                      ; The type (normal, fill or cell_fill) of the contour surface
            closed:0B, $                    ; Flag indicating if the contour lines are closed
            downhill:0B, $                  ; Flag indicating if downhill marks are drawn
            font:0B, $                      ; The character font for the annotations
            clip:0B, $                      ; Flag indicating if the contour is clipped
            visible:0B $                    ; Flag indicating if the contour is visible or not
           }

   struct_hide, class

END

